﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.UnityExtensions;
using Microsoft.Practices.Unity;
using MyFramework.Common;
using MyFramework.Common.Interfaces;
using MyFramework.Core;

namespace MyFramework.Shell
{
    /// <summary>
    /// my bootstrapper
    /// </summary>
    public abstract class MyBootstrapper : UnityBootstrapper
    {

        #region Fields

        #endregion

        #region Method Overrides

        /// <summary>
        /// Populates the Module Catalog.
        /// </summary>
        /// <returns>A new Module Catalog.</returns>
        /// <remarks>
        /// This method uses the Module Discovery method of populating the Module Catalog. It requires
        /// a post-build event in each module to place the module assembly in the module catalog
        /// directory.
        /// </remarks>
        protected override IModuleCatalog CreateModuleCatalog()
        {
            //DirectoryInfo directory = new DirectoryInfo(@".\Modules");
            //if (!directory.Exists)
            //{
            //    directory.Create();
            //}

            var moduleCatalog = new OrderDirectoryModuleCatalog();
            //moduleCatalog.ModulePath = @".\Modules";
            moduleCatalog.ModulePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            foreach (var item in GetMainModule().Where(r =>
            {
                var interfaces = r.GetInterfaces();
                var result = interfaces.Any(d => d == typeof(IModule));
                return result;
            }))
            {
                var moduleInfo = new ModuleInfo(item.Name, item.AssemblyQualifiedName);
                moduleInfo.Ref = item.Assembly.Location;
                moduleInfo.State = ModuleState.NotStarted;
                moduleCatalog.AddModule(moduleInfo);
            }

            return moduleCatalog;
        }

        /// <summary>
        /// Gets the main module.
        /// </summary>
        /// <returns></returns>
        protected abstract List<Type> GetMainModule();

        /// <summary>
        /// Configures the default region adapter mappings to use in the application, in order 
        /// to adapt UI controls defined in XAML to use a region and register it automatically.
        /// </summary>
        /// <returns>The RegionAdapterMappings instance containing all the mappings.</returns>
        protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
        {
            // Call base method
            var mappings = base.ConfigureRegionAdapterMappings();
            if (mappings == null) return null;

            // Set return value
            return mappings;
        }

        /// <summary>
        /// Instantiates the Shell window.
        /// </summary>
        /// <returns>A new ShellWindow window.</returns>
        protected override DependencyObject CreateShell()
        {
            return (DependencyObject)GetShell();
        }

        /// <summary>
        /// Gets the shell.
        /// </summary>
        /// <returns></returns>
        protected abstract IView GetShell();

        /// <summary>
        /// Displays the Shell window to the user.
        /// </summary>
        protected override void InitializeShell()
        {
            base.InitializeShell();

            //MyApplication.Current.MainWindow = (Window)GetShell();
            MyApplication.Current.MainWindow.Show();
        }

        /// <summary>
        /// Configures the <see cref="T:Microsoft.Practices.Unity.IUnityContainer"/>. May be overwritten in a derived class to add specific
        /// type mappings required by the application.
        /// </summary>
        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();
            this.RegisterElement();
        }

        /// <summary>
        /// Registers the element.
        /// </summary>
        protected virtual void RegisterElement()
        {
            //Container.RegisterType<IController,ControllerBase>(new ContainerControlledLifetimeManager());
            Container.RegisterInstance<IControllerFactory>(CommonUnityName.UNITY_FACTORY, new UnityControllerFactory(), new ContainerControlledLifetimeManager());

        }

        #endregion
    }
}
